﻿
using System;
using System.IO;
using System.Threading;
using MX.Core.Caching.Redis.Sider.Executors;

namespace MX.Core.Caching.Redis.Sider
{
	public partial class SiderRedisClient
	{
		private void invoke (string command)
		{
			invoke (command, (r, s) => (object)null);
		}

		private  T invoke<T> (string command,
		                      Func<ProtocolReader,Stream,  T> readAction)
		{
			return invoke<T> (command, 0, (w, s) => {
			}, readAction);
		}

		private  T invoke<T> (string command, string key,
		                      Func<ProtocolReader,Stream,  T> readAction)
		{
			return invoke<T> (command, 1, (w, s) => w.WriteArg (s, key), readAction);
		}

		private  T invoke<T> (string command, string key, byte[] value,
		                      Func<ProtocolReader,Stream,  T> readAction)
		{
			return invoke<T> (command, 2,
				(w, s) => {
					w.WriteArg (s, key);
					w.WriteArg (s, value);
				},
				readAction);
		}




		private T invoke<T> (
			string command, int numArgs,
			Action<ProtocolWriter,Stream> writeArgsAction,
			Func<ProtocolReader,Stream, T> readAction)
		{
			
			return invoke<T> (Invocation<T>.New (command, (w, s) => {
				w.WriteCmdStart (s, command, numArgs);
				writeArgsAction (w, s);
			}, readAction));
			 

		}

		private T invoke<T> (Invocation<T>  invocation)
		{

			if (Executor is PipelinedExecutor) {
				return (Executor as PipelinedExecutor).Execute (invocation);
			} else { 
				using (var socketIO =	SockIOPool.GetInstance ().GetSock (invocation.Command)) {
					return Executor.Execute (invocation, socketIO.Stream);
				}
			}

		}







	 
	}
}
